
#include "MsnCommand.h"
#include "Util.h"


MsnCommand::MsnCommand(const wxString& cmd, bool tr) : type(cmd), inTransaction(tr)
{
	if(inTransaction){
		transactionID = MsnCommandFactory::Get().NextTransactionID();
	}else{
		transactionID = -1;
	}
}

wxString MsnCommand::GetParameter(int index){
	if(parameterList.Count() > (unsigned int)index){
            return parameterList.Item(index);
	}

     return wxEmptyString;
}

int MsnCommand::GetParameterAsInt(int index){
        wxString value = GetParameter(index);
        if(value.IsEmpty()) return 0;

        return atoi(value.mb_str());
}

    void MsnCommand::SetParameter(const wxString& value)
    {
        parameterList.Add(value);
    }

    void MsnCommand::SetParameter(int value)
    {
        wxString buf;
		parameterList.Add(wxString::Format(_T("%d"),value));
    }

    void MsnCommand::SetParameter(int index, const wxString& value)
    {
        parameterList.Add(value);
    }

    int MsnCommand::GetParameterCount()
    {
        return parameterList.Count();
    }


wxString MsnCommand::toString()
{
    wxMemoryBuffer buf;
    ToBuffer(buf);
    return wxString((char*)buf.GetData(), wxConvUTF8, buf.GetDataLen());
}

void MsnCommand::ToBuffer(wxMemoryBuffer& buf)
{
    wxString str;
    str<<type;

	if(inTransaction){
        str<<_T(" ")<<transactionID;
	}

    int size = parameterList.GetCount();
    for(int i=0;i<size;i++){
        str<<_T(" ");
        str<<parameterList.Item(i);
    }

    str<<_T("\r\n");

    buf.AppendData(WS2C(str), WSLEN(str));
}

void MsnCommand::Parse(const wxString& line)
{
    wxStringTokenizer st(line,_T(" "));
    type = st.NextToken();

    if(inTransaction && st.HasMoreTokens()){
        transactionID = atoi(st.NextToken().mb_str());
    }

    while ( st.HasMoreTokens() ){
        wxString parameter = StringUtil::URLDecode(st.GetNextToken());
        parameterList.Add((parameter));
    }
}



IMPLEMENT_DYNAMIC_CLASS(InCommandVER, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandCVR, MsnCommand)

IMPLEMENT_DYNAMIC_CLASS(InCommandXFR, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandSYN, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandLSG, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandLST, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandILN, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandNLN, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandFLN, MsnCommand)

IMPLEMENT_DYNAMIC_CLASS(InCommandPRP, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandCHL, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandCHG, MsnCommand)

IMPLEMENT_DYNAMIC_CLASS(InCommandADC, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandADG, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandREM, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandRMG, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandREG, MsnCommand)

IMPLEMENT_DYNAMIC_CLASS(InCommandRNG, MsnCommand)
//IMPLEMENT_DYNAMIC_CLASS(InCommandQRY, MsnCommand)

IMPLEMENT_DYNAMIC_CLASS(InCommandUSR, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandMSG, MsnCommand)

IMPLEMENT_DYNAMIC_CLASS(InCommandACK, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandNAK, MsnCommand)

IMPLEMENT_DYNAMIC_CLASS(InCommandCAL, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandJOI, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandANS, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandIRO, MsnCommand)
IMPLEMENT_DYNAMIC_CLASS(InCommandBYE, MsnCommand)

IMPLEMENT_DYNAMIC_CLASS(InCommandFIL, MsnCommand)

MsnCommandFactory::MsnCommandFactory()
{
	value = 0;
}

MsnCommandFactory& MsnCommandFactory::Get()
{
	static MsnCommandFactory instance;
	return instance;
}

MsnCommand* MsnCommandFactory::CreateCommand(const wxString& line)
{
    wxString type = line.BeforeFirst(' ');
    wxString className = _T("InCommand")+type;
    //Debug(_("Command class -->")+className);
    MsnCommand* cmd = (MsnCommand*)wxCreateDynamicObject(className);

    if(!cmd){
        cmd = new InCommandOther();
    }

    cmd->Parse(line);

    return cmd;
}


int MsnCommandFactory::NextTransactionID()
{
	wxMutexLocker lock(mutex);
    return ++value;
}